package cn.ycl.auth.biz.menu.service.impl;

import cn.ycl.auth.biz.menu.dao.MenubarDao;
import cn.ycl.auth.biz.menu.entity.Menubar;
import cn.ycl.auth.biz.menu.service.MenubarService;
import cn.ycl.auth.biz.rolemenu.entity.RoleMenu;
import cn.ycl.auth.biz.rolemenu.service.RoleMenuService;
import cn.ycl.auth.biz.usercenter.service.RoleService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * (Menubar)表服务实现类
 *
 * @author makejava
 * @since 2020-12-03 20:50:05
 */
@Service("MenubarService")
public class MenubarServiceImpl implements MenubarService {
    @Resource
    private MenubarDao menubarDao;
    @Resource
    private RoleService roleService;
    @Resource
    private RoleMenuService roleMenuService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Menubar queryById(Long id) {
        return this.menubarDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Menubar> queryAllByLimit(int offset, int limit) {
        return this.menubarDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param Menubar 实例对象
     * @return 实例对象
     */
    @Override
    public Menubar insert(Menubar Menubar) {
        this.menubarDao.insert(Menubar);
        return Menubar;
    }

    /**
     * 修改数据
     *
     * @param menubar 实例对象
     * @return 实例对象
     */
    @Override
    public Menubar update(Menubar menubar) {
        this.menubarDao.update(menubar);
        return this.queryById(menubar.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.menubarDao.deleteById(id) > 0;
    }


    @Override
    public List<Menubar> getMenuTree(Long userId) {
        List<Long> roleIds = roleService.selectRoleIdsByUserId(userId);
        List<RoleMenu> roleMenus = new ArrayList<>();
        HashSet<Long> menuIds = new HashSet<>();
        roleIds.forEach(roleId -> roleMenus.addAll(roleMenuService.queryByRoleId(roleId)));
        //去重
        roleMenus.forEach(roleMenu -> menuIds.add(roleMenu.getMenuId()));
        List<Menubar> byMenuIds = menubarDao.findByMenuIds(menuIds);
        return transToTree(byMenuIds);
    }

    /**
     * 将列表数据转化成树形数据
     *
     * @param nodes
     * @return
     */
    private List<Menubar> transToTree(List<Menubar> nodes) {
        if (CollectionUtils.isEmpty(nodes)) {
            return new ArrayList<>();
        }
        Map<Long, List<Menubar>> menuListMap = transToMap(nodes);
        List<Menubar> treeNodes = new ArrayList<>();
        buildTreeNode(0L, treeNodes, menuListMap);
        return treeNodes;
    }

    /**
     * 重复key处理成一个集合
     *
     * @param menus
     * @return
     */
    private Map<Long, List<Menubar>> transToMap(List<Menubar> menus) {
        return menus.stream()
                .collect(Collectors.toMap(Menubar::getParentId, menubar -> {
                    List<Menubar> menubars = new ArrayList<>();
                    menubars.add(menubar);
                    return menubars;
                }, (List<Menubar> m1, List<Menubar> m2) -> {
                    m1.addAll(m2);
                    return m1;
                }));
    }

    /**
     * 构建树型数据
     *
     * @param parentId
     * @param treeNodes
     * @param menuListMap
     */
    private void buildTreeNode(Long parentId, List<Menubar> treeNodes, Map<Long, List<Menubar>> menuListMap) {
        if (!menuListMap.containsKey(parentId)) {
            return;
        }
        List<Menubar> Menubars = menuListMap.get(parentId);
        if (CollectionUtils.isEmpty(treeNodes)) {
            treeNodes.addAll(Menubars);
        } else {
            Menubar tmpNodeChildren = treeNodes.stream().filter(m -> Objects.equals(parentId, m.getId()))
                    .collect(Collectors.toList()).get(0);
            tmpNodeChildren.setChildren(Menubars);
        }

        for (Menubar Menubar : Menubars) {
            buildTreeNode(Menubar.getId(), Menubars, menuListMap);
        }
    }
}